import './LayoutPage.scss'
import { v4 } from 'uuid'
import { useRef, useState } from 'react'
import { useRequest } from 'alova/client'
import GridLayout from 'react-grid-layout'
import { useEventEmitter, useMount, useSize } from 'ahooks'
import { PlusOutlined, LayoutOutlined } from '@ant-design/icons'
import { Skeleton, FloatButton, Dropdown, Button, App } from "antd"

import { Http } from '../../Utils/Api'
import { removeTreeByKey, replaceNodeById } from '../../Utils'
import { TemplateCommon } from '../../Temp/Common'
import { Encrypt, Decrypt, GetIndexedDB } from '../../Utils/IndexedDB'
import { modelStore, drawerStore } from '../../Config/zustand'
import { AdminRouter } from '../../Config/default'

const { port } = window.location

const LayoutPage = ({ url, uuid }) => {

    const { updateModel } = modelStore()
    const { updateDrawer } = drawerStore()
    const LayoutBox = useRef()
    const jsonPage = `LayoutPage/${url}`
    const { message, modal, notification } = App.useApp();
    const { send } = useRequest(data => Http(data), { immediate: false })
    const size = useSize(LayoutBox)
    const [userUuid, setUserUuid] = useState()
    const [layout, setlayout] = useState([])
    const [Status, setStatus] = useState(false)
    const [loading, setLoading] = useState(false)

    const onAddItem = () => {
        const newItem = { i: v4(), x: 0, y: 0, w: 1, h: 1 }
        setlayout(e => ([...e, newItem]))
    }

    const Items = (item) => {
        const { i, temp } = item
        return ([
            !temp && { key: 1, label: (<Button type='line' onClick={() => onSelect(i)}>选择模块</Button>) },
            temp && { key: 2, label: (<Button type='line' onClick={() => onConfig(item)}>配置模块</Button>) },
            temp?.[0] === 'C' && { key: 4, label: (<Button type='line' onClick={() => onConfigCharts(item)}>图例配置</Button>) },
            { key: 3, label: (<Button type='line' danger onClick={() => onDelete(i)}>删除模块</Button>) },
        ])
    }

    const onSelect = (uuid) => {
        updateModel({ type: 'CommonModel', width: 1200, title: '模块选择', data: { uuid, type: 'customModule', DateEvent: TemEvent } })
    }

    const onConfig = (item) => {
        const { i, temp, params } = item
        const formItem = TemplateCommon[temp].params
        updateDrawer({
            type: 'CommonModel',
            width: 640,
            title: '模块配置',
            data: { uuid: i, formItem, initData: params, type: 'customModuleParams', DateEvent: TemEvent }
        })
    }

    const onConfigCharts = (item) => {
        const { temp, params } = item
        updateDrawer({
            type: 'CommonCharts',
            title: TemplateCommon[temp].title + '配置',
            width: 800,
            data: { type: temp, item, params, DateEvent: TemEvent }
        })
    }

    const onDelete = (uuid) => {
        const data = removeTreeByKey(layout, uuid, 'i')
        setlayout(data)
    }

    const inInitFiles = async () => {
        send({ method: 'post', url: 'dictionary/SaveJsonInfoByUuid', params: { uuid: jsonPage, content: JSON.stringify(await Encrypt([])) } }).then(res => {
            notification.success({ message: '生成成功', description: '配置文件已生成成功!' })
            setStatus(true)
        })
    }

    const onSelectTemp = (data) => {
        const { uuid, name } = data
        if (name[0] === 'C') {
            layout.find(v => v.i === uuid).temp = name
            layout.find(v => v.i === uuid).chart = AdminRouter[name]
            setlayout([...layout])
        } else {
            layout.find(v => v.i === uuid).temp = name
            setlayout([...layout])
        }
    }

    const onSetParams = (data) => {
        const { uuid, params } = data
        layout.find(v => v.i === uuid).params = params
        setlayout([...layout])
    }

    const onSetChart = (data) => {
        const { uuid, ...item } = data
        const { chart } = layout.find(v => v.i === uuid)
        const obj = { ...chart, ...item }
        layout.find(v => v.i === uuid).chart = obj
        setlayout([...layout])
    }

    const CallBackFunc = (e) => {
        // console.log('CallBackFunc', e)
        const { type, data } = e
        const MapReturn = new Map([
            ['onSelectTemp', () => onSelectTemp(data)],
            ['onFormBack', () => onSetParams(data)],
            ['setChart', () => onSetChart(data)],
        ])
        const func = MapReturn.get(type)
        return func && func()
    }

    const TemEvent = useEventEmitter()
    TemEvent.useSubscription(CallBackFunc)

    useMount(async () => {
        const { userUuid } = await GetIndexedDB('user')
        setUserUuid(userUuid)
        getData()
    })

    const getData = () => {
        send({ method: 'get', url: 'dictionary/GetJsonInfoByUuid', params: { uuid: jsonPage } }).then(async res => {
            setlayout(await Decrypt(res))
            setStatus(true)
        }).catch(() => {
            notification.info({
                key: 'devPage',
                message: '未获取到配置!',
                description: '请检测网络或联系管理员!',
                showProgress: true,
                actions: (port || userUuid === '1e99e116-6ec0-425c-87b4-64dd2ce458e2') && (<Button type='primary' onClick={inInitFiles}>{url} 生成新配置文件</Button>)
            })
        })
    }

    const onSave = async () => {
        if (loading) {
            send({ method: 'post', url: 'dictionary/SaveJsonInfoByUuid', params: { uuid: jsonPage, content: JSON.stringify(await Encrypt(layout)) } }).then(res => {
                notification.success({ message: '保存成功', description: '配置文件保存成功!' })
                setLoading(false)
            })
        } else {
            setLoading(true)
        }
    }

    const onChange = e => {
        const data = replaceFields(e, layout)
        setlayout(data)
    }

    const replaceFields = (arr1, arr2) => {
        for (const item2 of arr2) {
            const foundIndex = arr1.findIndex(item1 => item1.i === item2.i)
            if (foundIndex !== -1) {
                if (item2.temp !== undefined) arr1[foundIndex].temp = item2.temp
                if (item2.params !== undefined) arr1[foundIndex].params = item2.params
                if (item2.chart !== undefined) arr1[foundIndex].chart = item2.chart
            }
        }
        return arr1
    }

    if (Status) {
        return (
            <div className="LayoutPage" ref={LayoutBox} >
                {size ?
                    <GridLayout
                        className="GridLayout"
                        isDraggable={loading}
                        isResizable={loading}
                        layout={layout}
                        margin={[0, 0]}
                        cols={24}
                        rowHeight={size.height / 24}
                        width={size.width}
                        onDragStop={onChange}
                        onResizeStop={onChange}
                    >
                        {layout.map((item) => {
                            const { i, temp, params, chart } = item
                            return (
                                <div className='Item' key={i} style={loading ? { border: `1px solid #ccc` } : {}}>
                                    <Dropdown trigger={['contextMenu']} menu={{ items: loading ? Items(item) : [] }}>
                                        <div style={{ width: '100%', height: '100%' }}>
                                            {(() => {
                                                if (temp) {
                                                    const Template = TemplateCommon[temp].temp
                                                    return <Template params={params} chart={chart} />
                                                }
                                                else return <div className='notTemp'>未选择模块</div>
                                            })()}
                                        </div>
                                    </Dropdown>
                                </div>
                            )
                        })}
                    </GridLayout> :
                    <Skeleton active paragraph={{ rows: 24 }} />
                }
                {Status && (port || userUuid === '1e99e116-6ec0-425c-87b4-64dd2ce458e2') &&
                    <FloatButton.Group shape="square" style={{ insetInlineEnd: 24 }}>
                        {loading && <FloatButton onClick={() => onAddItem()} icon={<PlusOutlined />} />}
                        <FloatButton onClick={onSave} icon={<LayoutOutlined />} />
                    </FloatButton.Group>
                }
            </div>
        )
    } else {
        return <Skeleton active paragraph={{ rows: 24 }} />
    }

}

export default LayoutPage